#ifndef CMD_TELNET_READER_H
#define CMD_TELNET_READER_H
#include "mina/io_session.h"
#include "cmd_reader.h"

#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>


#define IAC     255             /* interpret as command: */
#define DONT    254             /* you are not to use option */
#define DO      253             /* please, you use option */
#define WONT    252             /* I won't use option */
#define WILL    251             /* I will use option */
#define SB      250             /* interpret as subnegotiation */
#define GA      249             /* you may reverse the line */
#define EL      248             /* erase the current line */
#define EC      247             /* erase the current character */
#define AYT     246             /* are you there */
#define AO      245             /* abort output--but let prog finish */
#define IP      244             /* interrupt process--permanently */          
#define BREAK   243             /* break */                    
#define DM      242             /* data mark--for connect. cleaning */        
#define NOP     241             /* nop */                      
#define SE      240             /* end sub negotiation */      
#define EOR     239             /* end of record (transparent mode) */        
#define ABORT   238             /* Abort process */            
#define SUSP    237             /* Suspend process */          
#define xEOF    236             /* End of file: EOF is already used... */   
#define TELOPT_BINARY   0       /* 8-bit data path */
#define TELOPT_ECHO     1       /* echo */
#define TELOPT_RCP      2       /* prepare to reconnect */
#define TELOPT_SGA      3       /* suppress go ahead */
#define TELOPT_NAMS     4       /* approximate message size */
#define TELOPT_STATUS   5       /* give status */
#define TELOPT_TM       6       /* timing mark */
#define TELOPT_RCTE     7       /* remote controlled transmission and echo */
#define TELOPT_NAOL     8       /* negotiate about output line width */
#define TELOPT_NAOP     9       /* negotiate about output page size */
#define TELOPT_NAOCRD   10      /* negotiate about CR disposition */
#define TELOPT_NAOHTS   11      /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD   12      /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD   13      /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS   14      /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD   15      /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD   16      /* negotiate about output LF disposition */
#define TELOPT_XASCII   17      /* extended ascii character set */
#define TELOPT_LOGOUT   18      /* force logout */
#define TELOPT_BM       19      /* byte macro */
#define TELOPT_DET      20      /* data entry terminal */
#define TELOPT_SUPDUP   21      /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22  /* supdup output */
#define TELOPT_SNDLOC   23      /* send location */
#define TELOPT_TTYPE    24      /* terminal type */
#define TELOPT_EOR      25      /* end or record */
#define TELOPT_TUID     26      /* TACACS user identification */
#define TELOPT_OUTMRK   27      /* output marking */
#define TELOPT_TTYLOC   28      /* terminal location number */
#define TELOPT_3270REGIME 29    /* 3270 regime */
#define TELOPT_X3PAD    30      /* X.3 PAD */
#define TELOPT_NAWS     31      /* window size */
#define TELOPT_TSPEED   32      /* terminal speed */
#define TELOPT_LFLOW    33      /* remote flow control */
#define TELOPT_LINEMODE 34      /* Linemode option */
#define TELOPT_XDISPLOC 35      /* X Display Location */
#define TELOPT_OLD_ENVIRON 36   /* Old - Environment variables */
#define TELOPT_AUTHENTICATION 37/* Authenticate */
#define TELOPT_ENCRYPT  38      /* Encryption option */
#define TELOPT_NEW_ENVIRON 39   /* New - Environment variables */                                          
#define TELQUAL_IS      0       /* option is... */
#define TELQUAL_SEND    1       /* send option */
#define TELQUAL_INFO    2       /* ENVIRON: informational version of IS */
#define TELQUAL_REPLY   2       /* AUTHENTICATION: client version of IS */
#define TELQUAL_NAME    3       /* AUTHENTICATION: client version of IS */


//static unsigned char DO_ECHO[4] = {IAC, DO, TELOPT_ECHO, '\0'};
//static unsigned char WILL_ECHO[4] = {IAC, WILL, TELOPT_ECHO, '\0'};
static unsigned char WONT_ECHO[4] = {IAC, WONT, TELOPT_ECHO, '\0'};
//static unsigned char WILL_SGA[4] = {IAC, WILL, TELOPT_SGA, '\0'};
//static unsigned char WILL_TTYPE[4] = {IAC, WILL, TELOPT_TTYPE, '\0'};
//static unsigned char DO_TTYPE[4] = {IAC, DO, TELOPT_TTYPE, '\0'};
//static unsigned char SEND_TTYPE[7] = {IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE, '\0'};
//static unsigned char WONT_TTYPE[4] = {IAC, WONT, TELOPT_TTYPE, '\0'};
//static unsigned char WILL_NAWS[4] = {IAC, WILL, TELOPT_NAWS, '\0'};
//static unsigned char DO_NAWS[4] = {IAC, DO, TELOPT_NAWS, '\0'};
//static unsigned char WILL_TSPEED[4] = {IAC, WILL, TELOPT_TSPEED, '\0'};
//static unsigned char DO_TSPEED[4] = {IAC, DO, TELOPT_TSPEED, '\0'};
//static unsigned char SEND_TSPEED[7] = {IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE, '\0'};
//static unsigned char WONT_TSPEED[4] = {IAC, WONT, TELOPT_TSPEED, '\0'};
//static unsigned char WILL_LFLOW[4] = {IAC, WILL, TELOPT_LFLOW, '\0'};
//static unsigned char DO_LFLOW[4] = {IAC, DO, TELOPT_LFLOW, '\0'};
//static unsigned char WILL_LINEMODE[4] = {IAC, WILL, TELOPT_LINEMODE, '\0'};
//static unsigned char DONT_LINEMODE[4] = {IAC, DONT, TELOPT_LINEMODE, '\0'};
//static unsigned char WILL_NEW_ENVIRON[4] = {IAC, WILL, TELOPT_NEW_ENVIRON, '\0'};
//static unsigned char DO_NEW_ENVIRON[4] = {IAC, DO, TELOPT_NEW_ENVIRON, '\0'};
//static unsigned char SEND_NEW_ENVIRON[7] = {IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE, '\0'};
//static unsigned char WONT_NEW_ENVIRON[4] = {IAC, WONT, TELOPT_NEW_ENVIRON, '\0'};
//static unsigned char DO_STATUS[4] = {IAC, DO, TELOPT_STATUS, '\0'};
//static unsigned char WILL_STATUS[4] = {IAC, WILL, TELOPT_STATUS, '\0'};
static unsigned char DO_XDISPLOC[4] = {IAC, DO, TELOPT_XDISPLOC, '\0'};
//

namespace vpm 
{
	namespace cmo 
	{

		using namespace vpm::mina;
		class CmdTelnetReader : public CmdReader
		{
		public:
			CmdTelnetReader(IoSession & session):CmdReader(),m_ioSession(session),m_readThread(boost::bind(&CmdTelnetReader::read,this))
			{
				m_cmdUserSession.reset(new CmdUserSession(m_cmdView));
				CmdUserSessionAccess::attach_char_writer(*m_cmdUserSession,boost::bind(&CmdTelnetReader::write_char,this, _1)); 
				CmdUserSessionAccess::attach_string_writer(*m_cmdUserSession,boost::bind(&CmdTelnetReader::write_string,this, _1));				
			}

			~CmdTelnetReader()
			{
				this->stop_read();
				m_readThread.join();				
			}
			
			virtual char read_char()
			{			
				char buf[2];
				TcpMessageContext tcpMsg(buf,1);
				int ret = m_ioSession.read(tcpMsg);
				if (ret <=0 )
				{
					return 0;
				}
				return buf[0];	
			}

			virtual std::string read_string()   //same as readline 
			{
				return std::string(); 
			}

			virtual void write_char(char ch) 
			{			
				TcpMessageContext tcpMsg(&ch, 1);
				m_ioSession.write(tcpMsg);		
			}

			virtual void write_string(const char * pStr) 
			{
				TcpMessageContext tcpMsg((char*)pStr, (int)strlen(pStr));
				m_ioSession.write(tcpMsg);
			}

		private:			
			IoSession &m_ioSession;		
			boost::thread m_readThread;
		};

		typedef boost::shared_ptr<CmdTelnetReader> CmdTelnetReaderPtr; 
	}
}



#endif // 
  
